package pers.cfeng.server.dataManage.pageCache;

import pers.cfeng.common.DatabaseException;
import pers.cfeng.common.ErrorCode;
import pers.cfeng.server.dataManage.page.Page;
import pers.cfeng.server.utils.FaultHandler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

/**
 * @author Cfeng
 * 对于缓存资源page的缓存整体策略
 */

public interface PageCache {

    //新建页面
    int newPage(byte[] initData);

    //通过pgNO获取页面
    Page getPage(int pageNo) throws Exception;

    //关闭缓存
    void close();

    //释放当前页
    void release(Page page);

    //删除pageNo之后的所有页面
    void truncateAfterPageNo(int pageNo);

    //获取页号
    int getPageNo();

    //刷新页面
    void flushPage(Page page);

    /**
     * Page也是操作文件，所以接口中和vm一样提供创建文件和open两种操作
     */
    static PageCacheImpl create(String path, long memory) {
        File file = new File(path + PageCacheConstant.DB_SUFFIX);
        try {
            if(!file.createNewFile()) {
                FaultHandler.forcedStop(new DatabaseException(ErrorCode.FILE_EXISTS));
            }
        } catch (Exception e) {
            FaultHandler.forcedStop(e);
        }
        if(!file.canRead() || !file.canWrite()) {
            FaultHandler.forcedStop(new DatabaseException(ErrorCode.FILE_CANNOT_READ_OR_WRITE));
        }
        //NIO
        RandomAccessFile raf = null;
        FileChannel fc = null;
        try {
            raf = new RandomAccessFile(file, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
            FaultHandler.forcedStop(e);
        }
        return new PageCacheImpl((int)memory/PageCacheConstant.PAGE_SIZE, raf, fc);
    }

    static PageCacheImpl open(String path, long memory) {
        File file = new File(path + PageCacheConstant.DB_SUFFIX);
        if(!file.exists()) {
            FaultHandler.forcedStop(new DatabaseException(ErrorCode.FILE_NOT_EXIST));
        }
        if(!file.canRead() || !file.canWrite()) {
            FaultHandler.forcedStop(new DatabaseException(ErrorCode.FILE_CANNOT_READ_OR_WRITE));
        }
        //NIO
        RandomAccessFile raf = null;
        FileChannel fc = null;
        try {
            raf = new RandomAccessFile(file, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
            FaultHandler.forcedStop(e);
        }
        return new PageCacheImpl((int)memory/PageCacheConstant.PAGE_SIZE, raf, fc);
    }
}
